#include "ThreadPool.h"
#include "Result.h"
#include <chrono>

const int TASK_MAX_THREADHOLD = 1024;

ThreadPool::ThreadPool()
	:_threadSize(4),
	_taskSize(0),
	_taskQueMaxThreadHold(TASK_MAX_THREADHOLD),
	_pollMode(PollMode::MODE_FIXED)
{
}

ThreadPool::~ThreadPool()
{
}

void ThreadPool::setTaskMaxThreadHold(int threadhold)
{
	_taskQueMaxThreadHold = threadhold;
}

Result ThreadPool::submitTask(std::shared_ptr<Task> sp)
{
	std::unique_lock<std::mutex> lock(_taskQueMtx);

	if (!_notFull.wait_for(lock, std::chrono::seconds(1), [&]()->bool {
		return _taskQue.size() < (size_t)_taskQueMaxThreadHold;
		}))
	{
		std::cerr << "task queue is full,submit task fail" << std::endl;
		return Result(sp, false);
	}

	_taskQue.emplace(sp);
	_taskSize++;

	_notEmpty.notify_all();
	return Result(sp);
}

void ThreadPool::setMode(PollMode mode)
{
	_pollMode = mode;
}

void ThreadPool::start(int threadSize)
{
	_threadSize = threadSize;

	for (int i = 0; i < _threadSize; i++)
	{
		auto ptr = std::make_unique<Thread>(std::bind(&ThreadPool::threadHandler, this));
		_threads.emplace_back(std::move(ptr));
	}

	for (int i = 0; i < _threadSize; i++)
	{
		_threads[i]->start();
	}
}

void ThreadPool::threadHandler()
{
	for (;;)
	{
		std::shared_ptr<Task> task;
		{
			std::unique_lock<std::mutex> lock(_taskQueMtx);

			_notEmpty.wait(lock, [&]()->bool {
				return _taskQue.size() > 0;
				});

			task = _taskQue.front();
			_taskQue.pop();
			_taskSize--;

			if (_taskQue.size() > 0)
			{
				_notEmpty.notify_all();
			}
			_notFull.notify_all();
		}
		if (task != nullptr)
		{
			task->exec();
		}
	}
}




